<?php
/**
 * Created by PhpStorm.
 * User: Mysic
 * Date: 2020/12/23
 * Time: 17:04
 */

namespace app\common\mysic\profitShare\procedures;


use app\common\exception\BaseException;
use app\common\library\wechat\Abonus;
use app\common\library\wechat\WxPay;
use app\common\model\Order;
use app\common\model\VipCardOrder;
use app\common\model\Wxsetting;
use app\common\mysic\exceptions\EntityErrorException;
use app\common\mysic\MysicBase;
use app\mocks\extend\MockWeChatPay;
use app\mocks\extend\MockWeChatProfitSharing;
use think\Env;
use think\Exception;

class ProfitShare extends MysicBase
{
    const BONUS_REFUND = 1;//分红到微信
    const BONUS_REWARD = 2;//分红到赏金
    const BONUS_BALANCE = 3;//分红到零钱

    const API_TYPE_REFUND = 1;
    const API_TYPE_PROFIT_SHARING = 2;

    /** @var Abonus */
    public $abonusApi;
    /** @var WxPay */
    public $wxPay;
    /** @var VipCardOrder */
    protected $vipOrderModel;

    public function __construct()
    {
        parent::__construct();
        $this->vipOrderModel = new VipCardOrder();
        if(Env::get('mock.pay')) {
            $this->wxPay          = MockWeChatPay::instance();
            $this->abonusApi  = MockWeChatProfitSharing::instance();
        } else {
            $this->wxPay          = new WxPay();
            $this->abonusApi  = new Abonus();
        }
    }

    public function calculateProfit($profitAmount, $profitUpperLimit, $receivesAmount): string
    {
        if(0 == $receivesAmount) {
            $receivesAmount = 1;
        }
        $profit = bcdiv($profitAmount, $receivesAmount, 2) ?? '0';
        if(bccomp($profitUpperLimit, $profit, 2) < 0) {
            $profit = $profitUpperLimit;
        }
        return $profit;
    }

    public function calculateProfitAmount(Order $userOrderEntity, Wxsetting $wxSettingEntity): string
    {
        if(!$userOrderEntity->getData()) {
            throw new EntityErrorException('用户订单实体数据不存在');
        }
        if(!$wxSettingEntity->getData()) {
            throw new EntityErrorException('商户小程序设置实体数据不存在');
        }
        $rewardRate = bcdiv(strval($wxSettingEntity->rewardpercent), '100',2);
        $systemProfitSharingRate = '0.01';
        $rewardRate = bcsub($rewardRate, $systemProfitSharingRate,2);
        return bcmul($userOrderEntity->pay_price , $rewardRate,2);
    }

    public function calculateProfitUpperLimit(Order $userOrderEntity, Wxsetting $wxSettingEntity): string
    {
        return bcmul(strval($userOrderEntity->pay_price), bcdiv(strval($wxSettingEntity->upline), '100',2),2);
    }

    public function convertVipBonusPercent(Order $userOrderEntity, Wxsetting $wxSettingEntity, VipCardOrder $vipOrderEntity): ProfitShare
    {
        if(!$wxSettingEntity->getData()) {
            throw new EntityErrorException('商户小程序设置实体数据不存在');
        }
        if($userOrderEntity->order_source == 40 && $vipOrderEntity->bonus_percent > 0) {
            $wxSettingEntity->rewardpercent = $vipOrderEntity->bonus_percent;
        }
        return $this;
    }

    public function finishProfitSharing(Order $userOrderEntity, $description = '分账已完结'): bool
    {
        try {
            $this->abonusApi->setUserOrder($userOrderEntity)->dividendOver($description);
            $finishProfitSharingResponse = $this->abonusApi->getResponse();
            $this->log->info(json_encode($finishProfitSharingResponse, JSON_UNESCAPED_UNICODE), '调用微信完结分账接口返回值');
            RuntimeVariables::setWxFinishProfitSharingResponse($finishProfitSharingResponse ?? []);
        } catch (BaseException | Exception $e) {
            $this->log->error(exceptionLogFormat($e), '分账订单完结时抛出异常');
            return false;
        }
        if($finishProfitSharingResponse['return_code'] != 'SUCCESS') {
            $this->log->error($finishProfitSharingResponse['return_msg'], '微信完结分账接口通信失败');
            return false;
        }
        if($finishProfitSharingResponse['result_code'] != 'SUCCESS') {
            $this->log->error($finishProfitSharingResponse['result_err_code_des'], '微信完结分账业务失败');
            return false;
        }
        return true;
    }

    public function getProfitShareSnByOrderNo($orderNo): string
    {
        return $this->profitShareSnMap[$orderNo] ?? '';
    }

    public function orderRefundApply(Order $userOrderEntity, array $wxConfig, $refundMoney, $outRefundNo): bool
    {
        $this->wxPay->setConfigArr($wxConfig);
        try {
            $this->wxPay->refund($userOrderEntity->transaction_id, $userOrderEntity->pay_price, $refundMoney, $outRefundNo);
        } catch (BaseException|\Exception $e) {
            $this->log->error(exceptionLogFormat($e), '调用微信退款接口时抛出异常');
        }
        $refundApplyResponse = $this->wxPay->getResponse();
        $this->log->info(json_encode($refundApplyResponse, JSON_UNESCAPED_UNICODE), '调用微信退款申请接口返回值');
        RuntimeVariables::setWxProfitSharingApplyResponse($refundApplyResponse ?? []);
        if($refundApplyResponse['return_code'] != 'SUCCESS') {
            $this->log->error($refundApplyResponse['return_msg'], '退款申请通信失败');
            return false;
        }
        if($refundApplyResponse['result_code'] != 'SUCCESS') {
            $this->log->error($refundApplyResponse['result_err_code_des'], '退款申请业务失败');
            return false;
        }
        return true;
    }

    public function orderRefundQuery(Order $userOrderEntity, $refundMoney): bool
    {
        $refundQueryResult = $this->wxPay->refundQuery($userOrderEntity->transaction_id, $userOrderEntity->pay_price, $refundMoney);
        if(!$refundQueryResult) {
            sleep(3);
            $ret = $this->orderRefundQuery($userOrderEntity, $refundMoney);
            if($ret) {
                return true;
            }
        }
        RuntimeVariables::setWxProfitSharingQueryResponse($this->wxPay->getResponse());
        return true;
    }

    public function addProfitSharingReceivers($receivesEntities, $userEntities): bool
    {
        $validReceivesEntities = [];
        foreach($receivesEntities as $receivesEntity) {
            $receiver = [
                'type' => 'PERSONAL_OPENID',
                'account' => $userEntities[$receivesEntity->user_id]->open_id,
                'relation_type' => 'CUSTOM',
                'custom_relation' => '消费微股东'
            ];
            $this->log->info($receiver, '添加分账接收人');
            try {
                $this->abonusApi->addReceivers($receiver);
                $wxProfitShareAddReceiverResponse = $this->abonusApi->getResponse();
                $this->log->info($wxProfitShareAddReceiverResponse, '添加分帐人接口返回值');
                RuntimeVariables::setWxProfitShareAddReceiverResponse($wxProfitShareAddReceiverResponse, $receivesEntity->order_no);
                $ret = true;
                if($wxProfitShareAddReceiverResponse['return_code'] != 'SUCCESS' || $wxProfitShareAddReceiverResponse['result_code'] != 'SUCCESS') {
                    $ret = false;
                }
            } catch (BaseException | Exception $e) {
                $this->log->error(exceptionLogFormat($e), '添加分账接收人时抛出异常');
                $ret = false;
            }
            if(!$ret) {
                continue;
            }
            $validReceivesEntities[$receivesEntity->order_no] = $receivesEntity;
        }
        RuntimeVariables::setReceivesEntities($validReceivesEntities);
        return true;
    }

    public function makeProfitSharingApplyReceivers($receivesEntities, $userEntities, $receivesLogEntities): array
    {
        $receivers = [];
        foreach($receivesEntities as $receivesEntity) {
            $receivers[] = [
                'type' => 'PERSONAL_OPENID',
                'account' => $userEntities[$receivesEntity->user_id]->open_id,
                'amount' => intval(bcmul(strval($receivesLogEntities[$receivesEntity->order_no]->refund_fee), '100')),
                'description' => '订单_'. $receivesLogEntities[$receivesEntity->order_no]->order_no . '分账|金额_' . $receivesLogEntities[$receivesEntity->order_no]->refund_fee
            ];
        }
        $this->log->info($receivers, '分账申请接口的分账接收人列表');
        return $receivers;
    }

    public function profitSharingApply(array $receivers, $profitSharingSn, $paidOrderTransactionId): bool
    {
        $ret = false;
        try {
            $ret = $this->abonusApi->profitSharingApply($receivers, $profitSharingSn, $paidOrderTransactionId);
            $wxProfitSharingApplyResponse = $this->abonusApi->getResponse();
            $this->log->info(json_encode($wxProfitSharingApplyResponse, JSON_UNESCAPED_UNICODE), '调用微信分账接口返回值');
            RuntimeVariables::setWxProfitSharingApplyResponse($wxProfitSharingApplyResponse);
        } catch (BaseException | Exception $e) {
            $this->log->error(exceptionLogFormat($e), '调用分账申请接口时抛出异常');
        }
        return $ret;
    }

    public function profitSharingQuery($profitSharingSn, $transactionId): bool
    {
        try {
            $ret = $this->abonusApi->profitSharingQuery($profitSharingSn, $transactionId);
        } catch (BaseException | Exception $e) {
            $this->log->error(exceptionLogFormat($e), '调用分账查询接口时抛出异常');
            $ret = false;
        }
        $wxProfitSharingQueryResponse = $this->abonusApi->getResponse();
        RuntimeVariables::setWxProfitSharingQueryResponse($wxProfitSharingQueryResponse);
        return $ret;
    }

    public function removeProfitSharingReceivers(array $receiversEntities): bool
    {
        foreach($receiversEntities as $receivesEntity) {
            try {
                $this->abonusApi->removeReceiver($receivesEntity->open_id, 'PERSONAL_OPENID');
                $wxRemoveReceiverResponse = $this->abonusApi->getResponse();
                RuntimeVariables::setWxProfitShareRemoveReceiverResponse($wxRemoveReceiverResponse);
            } catch (BaseException $e) {
                $this->log->error(exceptionLogFormat($e), '删除分账接收人时抛出异常');
                return false;
            }
        }
        return true;
    }



}